package com.cqjtu.eecs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cqjtu.eecs.entity.*;
import com.cqjtu.eecs.exception.NotFoundException;
import com.cqjtu.eecs.exception.ParamsErrorException;
import com.cqjtu.eecs.mapper.ProjectMapper;
import com.cqjtu.eecs.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqjtu.eecs.utils.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 培养方案 服务实现类
 * </p>
 *
 * @author  luojun
 * @since 2022-03-07
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {
    @Autowired
    private ITrainingProjectService trainingProjectService;
    @Autowired
    private ITrainingGoalBriefEntityService trainingGoalBriefEntityService;
    @Autowired
    private ITrainingGoalTemplateService trainingGoalTemplateService;
    @Autowired
    private ITrainingGoalService trainingGoalService;
    @Autowired
    private IGraduateRequirementTemplateService graduateRequirementTemplateService;
    @Autowired
    private IRequirementService requirementService;
    @Autowired
    private ITrainingProjectCourseService trainingProjectCourseService;
    @Autowired
    private IProjectCourseService projectCourseService;
    @Autowired
    private IGraduateRequirementTrainingGoalTemplateService graduateRequirementTrainingGoalTemplateService;
    @Autowired
    private IGoalRequirementService goalRequirementService;
    @Autowired
    private ICourseBackGraduateRequirementTemplateService courseBackGraduateRequirementTemplateService;
    @Autowired
    private ICourseRequirementService courseRequirementService;



    /**
     * 复制模板到具体的年级
     * @param majorCode 专业代码
     * @param year  年级
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyProject(String majorCode, Integer year) {
        Assert.notBlank(majorCode, new ParamsErrorException("The majorCode cannot be null or blank"));
        Assert.notNull(year, new ParamsErrorException("The year cannot be null"));
        // 判断是否已经存培养方案
        Project project = this.getOne(new LambdaQueryWrapper<Project>()
                .eq(Project::getMajorCode, majorCode).eq(Project::getGrade, year));
        if (project != null)
            return;
        //  判断该专业是否存在模板
        if (!trainingProjectService.hasTemplate(majorCode)){
            throw new NotFoundException("The major does not have template");
        }
        // 1.复制方案
        // 获取专业模板信息
        TrainingProject trainingProject = trainingProjectService.getOne(new LambdaQueryWrapper<TrainingProject>()
                .eq(TrainingProject::getMajorCode, majorCode));
        // 获取概述实体
        TrainingGoalBriefEntity entity = trainingGoalBriefEntityService.getOne(
                new LambdaQueryWrapper<TrainingGoalBriefEntity>()
                .eq(TrainingGoalBriefEntity::getMajorCode, majorCode));
        // 封装成project
        this.save(new Project(
                        null,
                        year,
                        majorCode,
                trainingProject.getVersionCode(),
                trainingProject.getVersionName(),
                trainingProject.getGraduateCredit(),
                entity.getTrainingGoalBrief(),
                trainingProject.getBasicYear()
        ));
        // 获取该project
        Project one = this.getOne(new LambdaQueryWrapper<Project>()
                .eq(Project::getGrade, year)
                .eq(Project::getMajorCode, majorCode));
        // 2.复制培养目标
        // 获取培养目标模板
        List<TrainingGoalTemplate> goalTemplates = trainingGoalTemplateService.list(
                new LambdaQueryWrapper<TrainingGoalTemplate>()
                        .eq(TrainingGoalTemplate::getMajorCode, majorCode));
        ArrayList<TrainingGoal> goals = new ArrayList<>();
        goalTemplates.forEach(item->{
            goals.add(
                    new TrainingGoal(null, one.getPid(),
                            item.getTrainingGoalCode(), item.getTrainingGoalDescription()));
        });
        trainingGoalService.saveBatch(goals);
        // 3.复制毕业要求
        // 获取毕业要求模板
        List<GraduateRequirementTemplate> requirementTemplates = graduateRequirementTemplateService.list(
                new LambdaQueryWrapper<GraduateRequirementTemplate>()
                        .eq(GraduateRequirementTemplate::getMajorCode, majorCode));
        ArrayList<Requirement> requirements = new ArrayList<>();
        requirementTemplates.forEach(item->{
            requirements.add(
                    new Requirement(null,
                            one.getPid(),
                            item.getGraduateRequirementCode(),
                            item.getGraduateRequirementBrief(),
                            item.getPreGraduateRequirementId()));
        });
        requirementService.saveBatch(requirements);
        // 4.复制课程
        // 获取课程
        List<TrainingProjectCourse> trainingProjectCourses = trainingProjectCourseService
                .list(new LambdaQueryWrapper<TrainingProjectCourse>()
                .eq(TrainingProjectCourse::getMajorCode, majorCode));
        ArrayList<ProjectCourse> projectCourses = new ArrayList<>();
        trainingProjectCourses.forEach(item->{
            projectCourses.add(new ProjectCourse(null,
                    one.getPid(), item.getCourseTypeId(), item.getCourseId(),
                    item.getCourseCode(), item.getTerm(), item.getCredit(),
                    item.getEvaluationMode(), item.getCourseProperty(), item.getPeriod(),
                    item.getTheoreticalPeriod(), item.getPracticalPeriod(), item.getComputerPeriod(),
                    item.getExperimentPeriod()));
        });
        projectCourseService.saveBatch(projectCourses);
        // 5.复制目标要求
        // 获取已复制的目标
        List<TrainingGoal> trainingGoals = trainingGoalService.list(
                new LambdaQueryWrapper<TrainingGoal>()
                        .eq(TrainingGoal::getPid, one.getPid()));
        // 获取已复制的要求
        List<Requirement> requirementList = requirementService.list(new LambdaQueryWrapper<Requirement>()
                .eq(Requirement::getPid, one.getPid()));
        // 获取目标要求模板
        List<Integer> requirementTemplateIdList = requirementTemplates.stream()
                .map(GraduateRequirementTemplate::getGraduateRequirementId)
                .collect(Collectors.toList());

        List<GraduateRequirementTrainingGoalTemplate> graduateRequirementTrainingGoalTemplates =
                graduateRequirementTrainingGoalTemplateService
                .listGraduateRequirementTrainingGoalTemplateByIdList(requirementTemplateIdList);
//        System.out.println("requirementTemplateIdList:"+requirementTemplateIdList);
//        System.out.println("graduateRequirementTrainingGoalTemplates："+graduateRequirementTrainingGoalTemplates);
        // 模板的id映射到编码
        Map<Integer, String> requirementTemplateIdToCode = requirementTemplates.stream()
                .collect(Collectors.toMap(
                        GraduateRequirementTemplate::getGraduateRequirementId,
                        GraduateRequirementTemplate::getGraduateRequirementCode
                ));
        Map<Integer, String> goalTemplateIdToCode = goalTemplates.stream()
                .collect(Collectors.toMap(
                        TrainingGoalTemplate::getTrainingGoalId,
                        TrainingGoalTemplate::getTrainingGoalCode
                ));
        // 具体编码映射到id
        Map<String, Integer> requirementCodeToId = requirementList.stream()
                .collect(Collectors.toMap(Requirement::getRequirementCode, Requirement::getRequirementId));

        Map<String, Integer> goalCodeToId = trainingGoals.stream()
                .collect(Collectors.toMap(TrainingGoal::getTrainingGoalCode, TrainingGoal::getTrainingGoalId));
        // 封装成list
        ArrayList<GoalRequirement> goalRequirements = new ArrayList<>();
        graduateRequirementTrainingGoalTemplates.forEach(item ->{
            goalRequirements.add(new GoalRequirement(
                    requirementCodeToId.get(requirementTemplateIdToCode.get(item.getGraduateRequirementId())),
                    goalCodeToId.get(goalTemplateIdToCode.get(item.getTrainingGoalId()))
                    ));
        });
        // 插入目标—要求
        goalRequirementService.saveBatch(goalRequirements);
        // 6.复制课程要求
        // 获取已复制的课程
        List<ProjectCourse> pCourse = projectCourseService
                .list(new LambdaQueryWrapper<ProjectCourse>()
                        .eq(ProjectCourse::getPid, one.getPid()));
        // 方案-课程模板课程Code映射到课程id
        Map<String, Integer> courseCodeToId = trainingProjectCourses.stream()
                .collect(Collectors.toMap(TrainingProjectCourse::getCourseCode,
                TrainingProjectCourse::getCourseId));
        // 具体方案-课程Id映射到方案id
        Map<Integer, Integer> courseIdToProjectCourseId = pCourse.stream().collect(Collectors
                .toMap(ProjectCourse::getCourseId, ProjectCourse::getProjectCourseId));//模板中的课程code不可用，每一届可能相同。
        // 获取模板课程-毕业要求
        List<CourseBackGraduateRequirementTemplate> courseRequirementTemplate = courseBackGraduateRequirementTemplateService
                .list(new LambdaQueryWrapper<CourseBackGraduateRequirementTemplate>()
                        .eq(CourseBackGraduateRequirementTemplate::getMajorCode, majorCode));
        List<CourseRequirement> courseRequirements = new ArrayList<>();
        courseRequirementTemplate.forEach(item->{
            courseRequirements.add(
                    new CourseRequirement(courseIdToProjectCourseId.get(courseCodeToId.get(item.getCourseCode())),
                            requirementCodeToId.get(requirementTemplateIdToCode.get(item.getGraduateRequirementId())),
                            item.getCourseGraduateRequirementBackWeight()
                            )
            );
        });
        // 插入
        courseRequirementService.saveBatch(courseRequirements);
    }
}
